"""The main Glulx execution loop"""

from opcodes import *

def executeLoop(vm):
	"The main interpreter loop"
	#	Set up some variables
	finishedExecuting = False

	#	Keep running until we've finished!
	while not finishedExecuting:
		#	If appropriate, do some OS-specific processing
		vm.IOSystems[2].tick()

		#	Get the current opcode
		opcode = vm.memory.read('B')[0]
		if opcode & 0x80:
			if opcode & 0x40:
				opcode &= 0x3F
				opcode = (opcode << 8) | vm.memory.read('B')[0]
				opcode = (opcode << 16) | vm.memory.read('H')[0]
			else:
				opcode &= 0x7F
				opcode = (opcode << 8) | vm.memory.read('B')[0]

		#	Get the operand list structure
		operands = vm.lookupOperands(opcode)
		if not operands:
			raise GlulxError("Encountered unknown opcode: %s" % opcode)

		#	Load the instruction's operands, moving the PC to the next instruction
		inst = vm.parseOperands(operands)

		print "\nopcode: " + hex(opcode)
		print inst

		#	Perform the opcode!
		if opcode == op_sub:
			vm.storeOperand(inst[0], inst[1][2], inst[1][0] - inst[1][1])

		elif opcode == op_call:
			arglist = vm.popArguments(inst[1][1], 0);
			vm.stack.pushCallstub(inst[0], inst[1][2]);
			vm.enterFunction(inst[1][0], inst[1][1], arglist);

		elif opcode == op_copy:
			vm.storeOperand(inst[0], inst[1][1], inst[1][0])

		elif opcode == op_setiosys:
			vm.setIOMode(inst[1][0], inst[1][1])

		elif opcode == op_glk:
			arglist = vm.popArguments(inst[1][1], 0)
			glkReturn = vm.IOSystems[2].perform(inst[1][0], inst[1][1], arglist)
			vm.storeOperand(inst[0], inst[1][2], glkReturn)

		else:
			finishedExecuting = True
